'use strict';
angular.module('Eamclient.services', [])

/** 
 * Persistence Object Manager
 * depends on understore
 */
.service('store', function($log, cfg) {

    this.saveUserProfile = function(data) {
        window.localStorage.setItem('EAM_USER_PROFILE', JSON.stringify(data));
    }


    this.deleteUserProfile = function() {
        // delete accessToken
        window.localStorage.removeItem('EAM_USER_PROFILE');
    }

    this.getUserProfile = function() {
        var data = window.localStorage.getItem('EAM_USER_PROFILE');
        if (data) {
            return JSON.parse(data);
        } else {
            return {};
        }
    };

    this.setAccessToken = function(data) {
        window.localStorage.setItem('EAM_ACCESS_TOKEN', JSON.stringify(data));
    };

    this.deleteAccessToken = function() {
        // delete accessToken
        window.localStorage.removeItem('EAM_ACCESS_TOKEN');
    }

    this.getAccessToken = function() {
        var token = window.localStorage.getItem('EAM_ACCESS_TOKEN');
        if (token) {
            return JSON.parse(token);
        } else {
            return {};
        }
    };

    /**
     * Inspection Work Orders Management
     */

    this.getInspectionById = function(id) {
        var temp = this.getInspections();
        return temp[id];
    }

    this.saveInspection = function(dt) {
        var temp = this.getInspections();
        if (temp[dt.id]) {
            $log.warn('store saveInspection', 'data exist, override old record.');
            delete temp[dt.id];
        }
        /**
         * TODO
         * resolve images path problem
         * In the real world, the images are all should accessed in a securer way
         *
         */
        var eam_root_cause = S(dt.eam_root_cause).replaceAll('/public/upload/', '{0}/public/upload/'.f(cfg.server)).s;
        var eam_repair_guide = S(dt.eam_repair_guide).replaceAll('/public/upload/', '{0}/public/upload/'.f(cfg.server)).s;;
        dt.eam_repair_guide = eam_repair_guide;
        dt.eam_root_cause = eam_root_cause;
        temp[dt.id] = dt;
        window.localStorage.setItem('EAM_WO_INSPECTION', JSON.stringify(temp));
    };

    this.getInspections = function() {
        var local = window.localStorage.getItem('EAM_WO_INSPECTION');
        if (local) {
            return JSON.parse(local);
        } else {
            return {};
        }
    };

    /**
     * Maintenance Work Order Management
     */

    this.getMaintenanceById = function(id) {
        var temp = this.getMaintenances();
        return temp[id];
    }

    this.saveMaintenance = function(dt) {
        var temp = this.getMaintenances();
        if (temp[dt.id]) {
            $log.warn('store saveMaintenance', 'data exist, override old record.');
            delete temp[dt.id];
        }
        /**
         * TODO
         * resolve images path problem
         * In the real world, the images are all should accessed in a securer way
         *
         */
        var eam_root_cause = S(dt.eam_root_cause).replaceAll('/public/upload/', '{0}/public/upload/'.f(cfg.server)).s;
        var eam_repair_guide = S(dt.eam_repair_guide).replaceAll('/public/upload/', '{0}/public/upload/'.f(cfg.server)).s;;
        dt.eam_repair_guide = eam_repair_guide;
        dt.eam_root_cause = eam_root_cause;
        temp[dt.id] = dt;
        window.localStorage.setItem('EAM_WO_MAINTENANCE', JSON.stringify(temp));
    };

    this.getMaintenances = function() {
        var local = window.localStorage.getItem('EAM_WO_MAINTENANCE');
        if (local) {
            return JSON.parse(local);
        } else {
            return {};
        }
    };

})

.service('webq', function($http, $q, $log, store, cfg) {

    this.login = function(username, pass) {
        var deferred = $q.defer();
        $log.warn('post --> {0}/signin'.f(cfg.server));
        $http.post('{0}/signin'.f(cfg.server), {
                name: username,
                pass: pass,
                device: 'mobile'
            }, {
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
                responseType: 'json'
            })
            .success(function(data, status, headers) {
                if (typeof data === 'object' && data.rc == 1) {
                    store.setAccessToken({
                        username: username.toLowerCase(),
                        access_token: data.accessToken
                    });
                    deferred.resolve(data.accessToken);
                } else {
                    $log.warn('Can not login server, reason:' + JSON.stringify(data));
                    deferred.reject((typeof err === 'object' && err.error) ? err.error : '服务器通信错误.')
                }
            })
            .error(function(err, status) {
                $log.error('Can not login server, status ' + status);
                $log.error(err);
                deferred.reject((typeof err === 'object' && err.error) ? err.error : '服务器通信错误.');
            });
        return deferred.promise;
    }

    // get user profile data by accessToken
    // also work as a validate of accessToken
    this.getMyProfile = function() {
        var deferred = $q.defer();
        $http.post('{0}/api/v1/accesstoken?accesstoken={1}'.f(cfg.server,
                store.getAccessToken().access_token), {
                'Accept': 'application/json'
            })
            .success(function(data, status) {
                $log.debug('getMyProfile', JSON.stringify(data));
                store.saveUserProfile(data);
                deferred.resolve();
            })
            .error(function(err, status) {
                $log.debug(err);
                deferred.reject();
            });
        return deferred.promise;
    }

    this.getEAMWorkOrder = function(id) {
        var deferred = $q.defer();
        $http.get('{0}/api/v1/eam/{1}?accesstoken={2}&&mdrender=false'.f(
                cfg.server, id, store.getAccessToken().access_token), {
                'Accept': 'application/json'
            })
            .success(function(data, status) {
                $log.debug('getEAMWorkOrder', JSON.stringify(data));
                if (data.error_msg) {
                    deferred.reject(data);
                } else {
                    deferred.resolve(data);
                }
            })
            .error(function(err, status) {
                $log.error('getEAMWorkOrder', err);
                deferred.reject(err);
            });
        return deferred.promise;
    }

    this.escalateMaintainenceToReport = function(data) {
        var deferred = $q.defer();
        data.escalation_type = 'maintenance_to_report';
        $http.post('{0}/api/v1/eam/escalate?accesstoken={1}'.f(cfg.server, store.getAccessToken().access_token),
                data, {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                })
            .success(function(data, status) {
                if (status == 200) {
                    deferred.resolve();
                } else if (data.error_msg) {
                    deferred.reject(data.error_msg);
                } else {
                    deferred.reject('UNKNOWN ERROR');
                }
            })
            .error(function(e, status) {
                deferred.reject(e);
            });

        return deferred.promise;
    }

    this.escalateInspToMaintainence = function(data) {
        var deferred = $q.defer();
        data.escalation_type = 'insp_to_maintenance';
        $http.post('{0}/api/v1/eam/escalate?accesstoken={1}'.f(cfg.server, store.getAccessToken().access_token),
                data, {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                })
            .success(function(data, status) {
                if (status == 200) {
                    deferred.resolve();
                } else if (data.error_msg) {
                    deferred.reject(data.error_msg);
                } else {
                    deferred.reject('UNKNOWN ERROR');
                }
            })
            .error(function(e, status) {
                deferred.reject(e);
            });

        return deferred.promise;
    }

})


/*
 * network manager is only available after cordova plugins are loaded.
 * if not, will get an error that says 'TypeError: undefined is not an object'
 * https://github.com/apache/cordova-plugin-network-information/blob/master/doc/index.md
 * iOS Quirks to support iPhone 5S,
 * iOS does not have specific info like WIFI, 3G ... just cellular or not
 * Network Status Array
 *   states[Connection.UNKNOWN] = 'Unknown connection';
 *   states[Connection.ETHERNET] = 'Ethernet connection';
 *   states[Connection.WIFI] = 'WiFi connection';
 *   states[Connection.CELL_2G] = 'Cell 2G connection';
 *   states[Connection.CELL_3G] = 'Cell 3G connection';
 *   states[Connection.CELL_4G] = 'Cell 4G connection';
 *   states[Connection.CELL] = 'Cell generic connection';
 *   states[Connection.NONE] = 'No network connection';
 */
.service('ntm', function($rootScope, $log) {

    var self = this;
    // start a agent process to run intervally
    // monitor the network switch event, make sure to call this interface
    // after cordova device ready event is fired.
    this.start = function() {
        var hasNetwork;
        setInterval(function() {
            try {
                // $rootScope.$broadcast('ntm:', JSON.parse(e.data));
                switch (self.getNetwork()) {
                    case -1:
                        $log.debug('network manager is only available after cordova plugins are loaded.');
                        break;
                    case 0:
                        if (typeof hasNetwork === 'undefined') {
                            hasNetwork = false;
                        } else if (hasNetwork) {
                            hasNetwork = false;
                            $rootScope.$broadcast('ntm', 'online2offline');
                        }
                        break;
                    case 1:
                        if (typeof hasNetwork === 'undefined') {
                            hasNetwork = true;
                        } else if (!hasNetwork) {
                            hasNetwork = true;
                            $rootScope.$broadcast('ntm', 'offline2online');
                        }
                        break;
                    default:
                        $log.error('UNKNOWN Network Status Type.');
                        break;
                }
            } catch (e) {
                $log.error(e);
            }
        }, 5000);
    };

    // current this method only supports iOS
    // 1 - online
    // 0 - offline
    // -1 - plugin is not loaded
    this.getNetwork = function() {
        if (navigator.connection && navigator.connection.type) {
            if (_.indexOf([Connection.WIFI, Connection.CELL], navigator.connection.type) != -1) {
                // network is available
                return 1;
            } else {
                // device is offline
                return 0;
            }
        } else {
            return -1;
        }
    };
})

// jpush service wrapper and proxy
.service('jpushp', function($rootScope, $log, webq, store, workorder) {

    var platform = device.platform;

    function _onMessage(data) {
        $log.info('jpushp _onMessage ' + JSON.stringify(data));
        // var content = bToObj.content;
        // console.log(content);
        // $rootScope.$broadcast('jpushp', bToObj);
        /**
         * what WO looks like ?
         * {
                "id": "54c88386e6771300e14d6802",
                "author_id": "54c881b478ec9f6d38508a9b",
                "eam_wind_turbine_id": "sasa",
                "eam_component_id": "sasa",
                "eam_root_cause": "<div class=\"markdown-text\"><p>sasasa</p>\n</div>",
                "eam_alarm_level": 3,
                "eam_maintain_toolkits": [
                    {
                        "icon": "/public/dummy-data/toolkit.jpg",
                        "footer": true,
                        "count": "1",
                        "name": "s1x"
                    }
                ],
                "eam_inspection_assignee": "mike001",
                "eam_wo_category": "inspection",
                "eam_repair_guide": "<div class=\"markdown-text\"><p>asasa</p>\n</div>",
                "eam_maintain_parts": [
                    {
                        "icon": "/public/dummy-data/part.png",
                        "footer": true,
                        "count": "1",
                        "name": "1xx"
                    }
                ],
                "eam_timestamp": "2015-01-28T06:36:54.778Z",
                "author": {
                    "loginname": "mike001",
                    "avatar_url": "//gravatar.com/avatar/1d4b69ca93d0e73e068427e37eed661b?size=48"
                }
            }
        */
        webq.getEAMWorkOrder(data.extras._id)
            .then(function(wo) {
                $log.debug('jpushp getEAMWorkOrder ' + JSON.stringify(wo));
                switch (wo.eam_wo_category) {
                    case 'inspection':
                        workorder.saveInspection(wo);
                        break;
                    case 'maintenance':
                        workorder.saveMaintenance(wo);
                        break;
                    default:
                        $log.warn('jpushp getEAMWorkOrder unknown type. ' + JSON.stringify(wo));
                        break;
                }
            }, function(err) {
                $log.error('jPushPluginreceiveMessageIniOSCallback', 'can not retrieve work order details from server.');
            });
    }

    this.startPluginInAndroid = function() {
        if (platform === 'Android') {
            window.plugins.jPushPlugin.init();
            window.plugins.jPushPlugin.setDebugMode(true);
        }
    }

    window.jPushPluginReceiveMessageInAndroidCallback = function(data) {
        try {
            var payload = JSON.parse(data);
            // alert(payload.extras['cn.jpush.android.EXTRA']);
            if (typeof payload.extras == 'object' &&
                typeof payload.extras['cn.jpush.android.EXTRA'] == 'object') {
                _onMessage({
                    content_type: payload['content_type'],
                    extras: payload.extras['cn.jpush.android.EXTRA']
                });
            }
        } catch (e) {
            alert(e);
        }
    }

    window.jPushPluginOpenNotificationInAndroidCallback = function(data) {
        // alert(data);
    }

    window.jPushPluginreceiveMessageIniOSCallback = function(data) {
        try {
            $log.debug("JPushPlugin:receiveMessageIniOSCallback--data:" + data);
            var bToObj = JSON.parse(data);
            _onMessage(bToObj);
        } catch (exception) {
            $log.error("JPushPlugin:receiveMessageIniOSCallback" + exception);
        }
    }

    this.setDebugModeFromIos = function() {
        if (platform == 'iOS') {
            window.plugins.jPushPlugin.setDebugModeFromIos();
        }
    }

    this.setAlias = function(alais) {
        window.plugins.jPushPlugin.setAlias(alais.toLowerCase());
    }
})

/**
 * Work Orders
 * @param  {[type]} ){} [description]
 * @return {[type]}       [description]
 */
.service('workorder', function($rootScope, $log, $q, webq, store) {

    /**
     * [handleInspectionWO description]
     * @param  {[type]} wo [description]
     * @return {[type]}    [description]
     */
    this.saveInspection = function(wo) {
        try {
            store.saveInspection(wo);
            $rootScope.$broadcast('wo:inspection', wo);
        } catch (e) {
            $log.error('workorder', e);
        }
    }

    this.saveMaintenance = function(wo) {
        try {
            store.saveMaintenance(wo);
            $rootScope.$broadcast('wo:maintenance', wo);
        } catch (e) {
            $log.error('workorder', e);
        }
    }
})

;
